package JET.graphics.jogl;

import JET.Constants;
import JET.graphics.elements.Face;
import JET.physics.Mass;
import JET.physics.RSpring;
import JET.physics.Spring;
import JET.physics.Wall;
import JET.physics.bodies.SpringBody;
import java.awt.Color;
import java.util.Collection;
import javax.media.opengl.GL;

/**
 *
 * @author raos
 */
public class GLHelper implements Constants{

    static double[] circle_x,
                    circle_y;
    static int      circle_n = 12;

    public static void initData() {
        GLHelper.initCircleData();
    }
    /**
     * Initializes circle vertices.
     * Spreds circle_n vertices on circle of radius == 1.
     * Those vertices are then used to draw a circle;
     */
    private static void initCircleData() {
        circle_x = new double[circle_n];
        circle_y = new double[circle_n];
        double angle = Math.PI*2/circle_n;
        for(int i=0 ; i<circle_n; i++) {
            circle_x[i] = Math.cos(i*angle);
            circle_y[i] = Math.sin(i*angle);
        }
    }

    /**
     * Sets OpenGL color by given awt color.
     * @param gl
     * @param c AWT color.
     */
    public static void setColor(GL gl, Color c) {
        gl.glColor3d((double)c.getRed()/256., (double)c.getGreen()/256., (double)c.getBlue()/256.);
    }
    /**
     * Renders filled circle of given radius.
     * @param gl
     * @param radius Radius of circle t fill.
     */
    public static void fillCircle(GL gl, double radius) {
        gl.glBegin(GL.GL_POLYGON);
        for(int i=0; i<circle_n; i++)
            gl.glVertex2d(circle_x[i]*radius, circle_y[i]*radius);
        
        gl.glEnd();
    }

    /**
     * Renders filled circle of given radius.
     * @param gl
     * @param radius Radius of circle t fill.
     */
    public static void drawCircle(GL gl, double radius) {
        gl.glBegin(GL.GL_LINE_STRIP);
        for(int i=0; i<circle_n; i++)
            gl.glVertex2d(circle_x[i]*radius, circle_y[i]*radius);
        gl.glVertex2d(circle_x[0]*radius, circle_y[0]*radius);

        gl.glEnd();
    }

    public static void drawSpringBody(GL gl, JoglGraphicPanel jgp, SpringBody sb) {
        gl.glLoadIdentity();
        gl.glTranslatef(jgp.viewX, jgp.viewY, 0);
        gl.glScaled(jgp.viewScale, jgp.viewScale, 0.);

        gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_FILL);

        Collection<Face> faceCol = sb.getFaceListSync();
        synchronized(faceCol) {
            for(Face f : faceCol) {
                GLHelper.setColor(gl, f.getColor());
                gl.glBegin(GL.GL_POLYGON);

                double[] x = f.getXPoints();
                double[] y = f.getYPoints();
                for(int i=0; i<x.length; i++)
                    gl.glVertex2d(x[i], y[i]);

                gl.glEnd();
            }
        }

        gl.glBegin(GL.GL_LINES);
        // Springs
        if (jgp.getScene().GC.isDrawSprings2d()) {
            GLHelper.setColor(gl, SPRINGBODY_SPRING_COLOR);
            Collection<Spring> springCol = sb.getSpringListSync();
            synchronized(springCol) {
                for(Spring s : springCol)
                    if (s.isAlive()) {
                        double x1 = s.getM1().getPosition().getX();
                        double y1 = s.getM1().getPosition().getY();
                        double x2 = s.getM2().getPosition().getX();
                        double y2 = s.getM2().getPosition().getY();

                        gl.glVertex2d(x1, y1);
                        gl.glVertex2d(x2, y2);
                }
            }
        }
        gl.glEnd();

        // Rotary springs
        if (jgp.getScene().GC.isDrawSprings2d()) {
            GLHelper.setColor(gl, SPRINGBODY_RSPRING_COLOR);
            gl.glLoadIdentity();
            gl.glTranslatef(jgp.viewX, jgp.viewY, 0);
            gl.glScaled(jgp.viewScale, jgp.viewScale, 0.);
            gl.glBegin(gl.GL_LINE_STRIP);
            
            Collection<RSpring> rSpringCol = sb.getRSpringListSync();
            synchronized(rSpringCol) {
                for(RSpring rs : rSpringCol) {
                    gl.glVertex2d(rs.getM1().getPosition().getX(), rs.getM1().getPosition().getY());
                    gl.glVertex2d(rs.getM2().getPosition().getX(), rs.getM2().getPosition().getY());
                    gl.glVertex2d(rs.getM3().getPosition().getX(), rs.getM3().getPosition().getY());
                }
                gl.glEnd();
           
                for(RSpring rs : rSpringCol) {
                    gl.glLoadIdentity();
                    gl.glTranslatef(jgp.viewX, jgp.viewY, 0);
                    gl.glScaled(jgp.viewScale, jgp.viewScale, 0.);
                    gl.glTranslated(rs.getM2().getPosition().getX(),rs.getM2().getPosition().getY(), 0);
                    GLHelper.setColor(gl, SPRINGBODY_RSPRING_ARC_COLOR);
                    GLHelper.drawCircle(gl, RSPRING_ARC_RADIUS);
                }
            }
        }

        gl.glLoadIdentity();
        gl.glTranslatef(jgp.viewX, jgp.viewY, 0);
        gl.glScaled(jgp.viewScale, jgp.viewScale, 0.);

        // Walls
        gl.glBegin(gl.GL_LINES);
        if (jgp.getScene().GC.isDrawWalls2d()) {
            GLHelper.setColor(gl, SPRINGBODY_BORDER_COLOR);
            for(Wall w : sb.getBorder().getWallList()) {
                double x1 = w.getM1().getPosition().getX();
                double y1 = w.getM1().getPosition().getY();
                double x2 = w.getM2().getPosition().getX();
                double y2 = w.getM2().getPosition().getY();

                gl.glVertex2d(x1, y1);
                gl.glVertex2d(x2, y2);
            }
        }
        gl.glEnd();

        //Masses
        if (jgp.getScene().GC.isDrawMasses2d()) {
            GLHelper.setColor(gl, Color.BLACK);
            Collection<Mass> massCol = sb.getMassListSync();
            synchronized(massCol) {
                for(Mass m : massCol) {
                    double r = (m.getMass()/2.);
                    gl.glLoadIdentity();
                    gl.glTranslatef(jgp.viewX, jgp.viewY, 0);
                    gl.glScaled(jgp.viewScale, jgp.viewScale, 0.);
                    gl.glTranslated(m.getPosition().getX(), m.getPosition().getY(), 0.);

                    GLHelper.fillCircle(gl, r);
                }
            }
        }
    }

    public static void drawGrid(GL gl, JoglGraphicPanel jgp, double dx, double dy) {
        gl.glLoadIdentity();
        gl.glTranslatef(jgp.viewX, jgp.viewY, 0);
        gl.glScaled(jgp.viewScale, jgp.viewScale, 0.);
    }
}
